# ===============================
# author: Paulo Trigo Silva (PTS)
# since: MAI.2010
# version: v03
# ===============================
# v02: inclui "principio do mundo fechado"
# ver: "Does Pellet support closed world reasoning?"
# em: http://clarkparsia.com/pellet/faq/closed-world/


#______________________________________________________________________________
# Baseado nos exemplos em:
# http://owlapi.sourceforge.net/documentation.html

#______________________________________________________________________________
# Python
import os
from leitorGravador import LeitorGravador, pathToStringURI, gravar

#______________________________________________________________________________
# Java
from org.semanticweb.owl.apibinding import OWLManager
from org.semanticweb.owl.io import RDFXMLOntologyFormat, OWLXMLOntologyFormat
from org.semanticweb.owl.model import AddAxiom
from java.net import URI



#______________________________________________________________________________
class DesenhadorOntologia( LeitorGravador ):
   def __init__( self, strPhysicalURI, strOntologyURI="" ):
      LeitorGravador.__init__( self, strPhysicalURI, strOntologyURI )
      # We need a data factory to create various object from.
      # Each ontology has a reference to a data factory that we can use.
      self.factory = self.manager.getOWLDataFactory();


   def criar( self ):
      # Now create the ontology; we use the ontology URI (not the physical URI)
      # (ask the manager to create the ontology)
      self.ontology = self.manager.createOntology( self.ontologyURI )
      
   
   def obterLiteral(self, strName, includeFragment=True ):
      return self.obterElemento( strName, self.factory.getOWLDataType, includeFragment )
   
   def obterClasse( self, strName, includeFragment=True ):
      # Get hold of references to strClassName
      # Note that the ontology does not contain strClassName
      # we simply get references to objects from a data factory that represent strClassName
      return self.obterElemento( strName, self.factory.getOWLClass, includeFragment )
   

   def obterPropriedade( self, strName, includeFragment=True ):
      # Tecnica identica 'a de "obterClasse"
      return self.obterElemento( strName, self.factory.getOWLObjectProperty, includeFragment )

   def obterPropriedadeDados(self, strName, includeFragment=True):
      return self.obterElemento(strName, self.factory.getOWLDataProperty, includeFragment) 

   def obterIndividuo( self, strName, includeFragment=True ):
      # Tecnica identica 'a de "obterClasse"
      return self.obterElemento( strName, self.factory.getOWLIndividual, includeFragment )


   def obterRestricaoExistencial( self, objectPropertyOWL, classOWL ):
      # uso directo da biblioteca; ver restantes metodos em "Interface OWLDataFactory"
      return self.factory.getOWLObjectSomeRestriction( objectPropertyOWL, classOWL )


   def obterRestricaoUniversal( self, objectPropertyOWL, classOWL ):
      # uso directo da biblioteca; ver restantes metodos em "Interface OWLDataFactory"
      return self.factory.getOWLObjectAllRestriction( objectPropertyOWL, classOWL )


   def obterComplemento( self, conceptOWL ):
      # uso directo da biblioteca; ver restantes metodos em "Interface OWLDataFactory"
      return self.factory.getOWLObjectComplementOf( conceptOWL )


   def obterInterseccao( self, conceptOWL_list ):
      # uso directo da biblioteca; ver restantes metodos em "Interface OWLDataFactory"
      return self.factory.getOWLObjectIntersectionOf( conceptOWL_list )


   def obterUniao( self, conceptOWL_list ):
      # uso directo da biblioteca; ver restantes metodos em "Interface OWLDataFactory"
      return self.factory.getOWLObjectUnionOf( conceptOWL_list )


   def obterConceitoUniversal( self ):
      return self.factory.getOWLThing()


   def obterConceitoAusencia( self ):
      return self.factory.getOWLNothing()
   

   def adicionarAxiomaIgualdade( self, leftConceptOWL, rightConceptOWL ):
      # Now create the axiom
      axiom = self.factory.getOWLEquivalentClassesAxiom( leftConceptOWL, rightConceptOWL)
      # We now add the axiom to the ontology, so that the ontology states that A is equivalent to B.
      # To do this we create an AddAxiom change object.
      addAxiom = AddAxiom( self.ontology, axiom )
      # We now use the manager to apply the change
      self.manager.applyChange( addAxiom )
      

   def adicionarAxiomaInclusao( self, subClassOWL, superClassOWL ):
      # Now create the axiom
      axiom = self.factory.getOWLSubClassAxiom( subClassOWL, superClassOWL)
      # We now add the axiom to the ontology, so that the ontology states that A is a subclass of B.
      # To do this we create an AddAxiom change object.
      addAxiom = AddAxiom( self.ontology, axiom )
      # We now use the manager to apply the change
      self.manager.applyChange( addAxiom )
    
   def adicionarSubPropriedade( self, subProperty, superProperty ):
      # create the axiom
		axiom = self.factory.getOWLSubObjectPropertyAxiom( subProperty, superProperty )
		# We now add the axiom to the ontology, so that the ontology states that A is a subSubProperty of B.
      # To do this we create an AddAxiom change object.
		addAxiom = AddAxiom( self.ontology, axiom )
		# We now use the manager to apply the change
		self.manager.applyChange( addAxiom )

   def adicionarAxiomaPertenca( self, individualOWL, conceptOWL ):
      # mecanismo identico ao dos axiomas (de inclusao e igualdade)
      axiom = self.factory.getOWLClassAssertionAxiom( individualOWL, conceptOWL )
      addAxiom = AddAxiom( self.ontology, axiom )
      self.manager.applyChange( addAxiom )
      # We now use the manager to apply the change
      self.manager.applyChange( addAxiom )

   def adicionarMundoFechado( self ):
      # "principio do mundo fechado"
      # ver: "Does Pellet support closed world reasoning?"
      # em: http://clarkparsia.com/pellet/faq/closed-world/
      Thing = self.obterConceitoUniversal()
      allReferencedIndividuals = self.ontology.getReferencedIndividuals()
      oneOf = self.factory.getOWLObjectOneOf( allReferencedIndividuals )
      self.adicionarAxiomaIgualdade( Thing, oneOf )


   def adicionarConceitoFechado( self, classOWL ):
      # "principio do mundo fechado"
      # ver: "Does Pellet support closed world reasoning?"
      # em: http://clarkparsia.com/pellet/faq/closed-world/
      classReferencedIndividuals = []
      for individual in self.ontology.getReferencedIndividuals():
         if classOWL in individual.getTypes( self.ontology ):
            classReferencedIndividuals.append( individual )
      oneOf = self.factory.getOWLObjectOneOf( classReferencedIndividuals )
      print oneOf
      self.adicionarAxiomaIgualdade( classOWL, oneOf )


   def adicionarPropriedade( self, propertyOWL, individualOWL, individualFillerOWL ):
      # Now create the actual assertion (triple), as an object property assertion axiom:
      # individualOWL --> propertyOWL --> individualFillerOWL
      assertion = self.factory.getOWLObjectPropertyAssertionAxiom( individualOWL, propertyOWL, individualFillerOWL )
      # To do this we create an AddAxiom change object.
      addAxiom = AddAxiom( self.ontology, assertion )
      # We now use the manager to apply the change
      self.manager.applyChange( addAxiom )


   def mostrarTBox( self ):
      strInclusao = " [="
      strIgualdade = " =="
      # Get all of the classes which are referenced in the ontology
      for classOWL in self.ontology.getReferencedClasses():
         print classOWL
         # axioma de inclusao (de classOWL)
         self.mostrarAxioma( classOWL, classOWL.getSuperClasses( self.ontology ), strInclusao )
         # axioma de igualdade (de classOWL)
         self.mostrarAxioma( classOWL, classOWL.getEquivalentClasses( self.ontology ), strIgualdade )


   def mostrarAxioma( self, classOWL, axiomSet, axiomSymbol ):
      if not axiomSet.isEmpty():
         print "  " + classOWL.toString() + axiomSymbol,
         for axiom in axiomSet: print axiom,
         print


   def mostrarABox( self ):
      # Get all of the individuals which are referenced in the ontology
      for individual in self.ontology.getReferencedIndividuals():
         print individual
         self.mostrarAssercaoPapel( individual, individual.getObjectPropertyValues( self.ontology ) )
         self.mostrarAssercaoConceito( individual, individual.getTypes( self.ontology ) )
         

   def mostrarAssercaoPapel( self, individual, assertionMap ):
      if not assertionMap.isEmpty():
         for predicate in assertionMap:
            print "  " + individual.toString(),
            print "%s %s" % ( predicate, assertionMap[ predicate ] ),
            print


   def mostrarAssercaoConceito( self, individual, assertionList ):
      if not assertionList.isEmpty():
         for assertion in assertionList:
            print "  " + individual.toString() + " in",
            print "%s" % ( assertion ),
            print


   #____________________________
   # Metodos Auxiliares (inicio)
   def obterElemento( self, strElement, elementFactory, includeFragment=True ):
      uri = self.obterElementoURI( strElement, includeFragment )
      return elementFactory( uri )

      
   def obterElementoURI( self, strElement, includeFragment=True ):
      fragmentLabel = "#"
      if not includeFragment: fragmentLabel = ""
      strElementURI = self.ontologyURI.toString() + fragmentLabel + strElement
      return URI.create( strElementURI )
   #_________________________
   # Metodos Auxiliares (fim)



#______________________________________________________________________________
# Funcoes Utilitarias



#______________________________________________________________________________
# Indicacao dos locais (URI) logico e fisico da ontologia
# URI: local logico da ontologia
ontologyURI = "http://www.rpc/ontologias/z_criar.owl"

# URI: local logico da ontologia
toPath = currentDir = os.getcwd() # pasta corrente
toFileName = "z_myOntoCriar.owl"
physicalURI = pathToStringURI( toPath, toFileName )

#______________________________________________________________________________
if __name__ == "__main__":
   o = DesenhadorOntologia( physicalURI, ontologyURI )
   o.criar()
   
   Pessoa = o.obterClasse( "Pessoa" )
   Homem = o.obterClasse( "Homem" )
   Mulher = o.obterClasse( "Mulher" )
   o.adicionarAxiomaInclusao( Homem, Pessoa )
   o.adicionarAxiomaInclusao( Mulher, Pessoa )
   
   #Mulher = Pessoa and Feminino
   Feminino = o.obterClasse( "Feminino" )
   Pessoa_and_Feminino = o.obterInterseccao( [Pessoa, Feminino] )
   o.adicionarAxiomaIgualdade( Mulher, Pessoa_and_Feminino )
   
   #Homem = Pessoa and not Mulher
   not_Mulher = o.obterComplemento( Mulher )
   Pessoa_and_not_Mulher = o.obterInterseccao( [Pessoa, not_Mulher] )
   o.adicionarAxiomaIgualdade( Homem, Pessoa_and_not_Mulher )
   
   #Mae = Mulher and temFilho some Pessoa
   Mae = o.obterClasse( "Mae" )
   temFilho = o.obterPropriedade( "temFilho" )
   existe_temFilho_Pessoa = o.obterRestricaoExistencial( temFilho, Pessoa )
   Mulher_and_existe_temFilho_Pessoa = o.obterInterseccao( [Mulher, existe_temFilho_Pessoa] )
   o.adicionarAxiomaIgualdade( Mae, Mulher_and_existe_temFilho_Pessoa )

   # < COMPLETAR >
   #Pai = Homem and temfilho some Pessoa
   Pai = o.obterClasse( "Pai" )
   Homem_and_existe_temFilho_Pessoa = o.obterInterseccao( [Homem, existe_temFilho_Pessoa] )
   o.adicionarAxiomaIgualdade( Pai,  Homem_and_existe_temFilho_Pessoa)
   
   #Progenitor = Pai or Mae
   Progenitor = o.obterClasse( "Progenitor" )
   Pai_or_Mae = o.obterUniao( [Pai, Mae] )
   o.adicionarAxiomaIgualdade( Progenitor,  Pai_or_Mae)
   
   #Avo = Mae and temFilho some Progenitor
   Avo = o.obterClasse( "Avo" )
   temFilho_some_Progenitor = o.obterRestricaoExistencial( temFilho, Progenitor )
   Mae_and_temFilho_some_Progenitor = o.obterInterseccao( [Mae, temFilho_some_Progenitor] )
   o.adicionarAxiomaIgualdade( Avo,  Mae_and_temFilho_some_Progenitor)
   
   
   
   pedro = o.obterIndividuo( "pedro" )
   maria = o.obterIndividuo( "maria" )
   joana = o.obterIndividuo( "joana" )
   o.adicionarPropriedade( temFilho, maria, pedro )
   o.adicionarPropriedade( temFilho, pedro, joana )

   o.adicionarAxiomaPertenca( pedro, Pessoa )
   o.adicionarAxiomaPertenca( maria, Pessoa )
   o.adicionarAxiomaPertenca( maria, Mulher )
   o.adicionarAxiomaPertenca( joana, Pessoa )
   o.adicionarAxiomaPertenca( joana, Mulher )

   outraProp = o.obterPropriedade( "outraProp" )
   o.adicionarPropriedade( outraProp, maria, pedro )
   
   print "-- /// --"
   o.mostrarTBox()
   print "-- /// --"
   o.mostrarABox()
   print "-- /// --"
   print "\nGravar (inicio)"
   o.gravar()
   print "Gravar (fim)\n"

   print "ontologyURI = " + o.ontologyURI.toString()
   print "physicalURI = " + o.physicalURI.toString()
   print "-- FIM --"
   
   
   


   print '\n\nBEGIN PIZZA'
   
   o = DesenhadorOntologia( pathToStringURI( os.getcwd(), "z_pizza.owl" ), "http://PIZZA" )
   o.criar()
   
   pizza = o.obterClasse( "Pizza" )
   namedPizza = o.obterClasse( "NamedPizza" )
   americanaPizza = o.obterClasse( "AmericanaPizza" )
   o.adicionarAxiomaInclusao( namedPizza, pizza )
   o.adicionarAxiomaInclusao( americanaPizza, namedPizza )
   
   
   pizzaBase = o.obterClasse( "PizzaBase" )
   deepPanBase = o.obterClasse( "DeepPanBase" )
   o.adicionarAxiomaInclusao( deepPanBase, pizzaBase )
   
   hasIngredient = o.obterPropriedade( "hasIngredient" )
   hasBase = o.obterPropriedade( "hasBase" )
   hasTopping = o.obterPropriedade( "hasTopping" )
   o.adicionarSubPropriedade( hasBase, hasIngredient )
   o.adicionarSubPropriedade( hasTopping, hasIngredient )

   print "-- /// --"
   o.mostrarTBox()
   print "\nGravar pizza (inicio)"
   o.gravar()
   print "Gravar (fim)\n"
   print "ontologyURI = " + o.ontologyURI.toString()
   print "physicalURI = " + o.physicalURI.toString()
   print '-- FIM PIZZA --'
   
   


